home *** CD-ROM | disk | FTP | other *** search
/ Amiga Tools 3 / Amiga Tools 3.iso / grafik / raytracing / rayshade-4.0.6.3 / raypaint / amigraphics.c next >
Encoding:
C/C++ Source or Header  |  1994-08-09  |  11.4 KB  |  526 lines

  1. /*
  2.  * The Amiga version of raypaint will open a 16 gray level black & white
  3.  * screen or a 8/32 color screen (depending on whether hires is required for
  4.  * the requested screen width or not) of the appropriate size. It will use
  5.  * hires, lace, overscan, or autoscroll to accommodate the entire picture.
  6.  * Both PAL and NTSC machines should be catered for.
  7.  * 
  8.  * If you have a three button mouse, the middle button should work as
  9.  * described in the README file. If you do not, pressing both mouse
  10.  * buttons will do the same thing (remember to deactivate any background
  11.  * programs like DMouse that use pressing both mouse buttons to flip
  12.  * between screens, etc). Some of these programs can be fooled by pressing
  13.  * the right mouse button first.
  14.  * 
  15.  * The code will only work on version 2.0 or higher of AmigaDOS.
  16.  * 
  17.  * Send comments and bug reports to:
  18.  * 
  19.  * Kriton Kyrimis    UUCP:     pythia!theseas!kriton!kyrimis
  20.  *             INTERNET: kyrimis@theseas.ntua.gr
  21.  */
  22.  
  23. #include <stdio.h>
  24. #include <exec/types.h>
  25. #include <exec/nodes.h>
  26. #include <exec/lists.h>
  27. #include <exec/ports.h>
  28. #include <dos/dos.h>
  29. #include <intuition/intuition.h>
  30. #include <intuition/classes.h>
  31. #include <graphics/gfxbase.h>
  32. #include <graphics/view.h>
  33. #include <graphics/graphint.h>
  34. #include <utility/tagitem.h>
  35.  
  36. #ifdef __SASC
  37. #include <proto/exec.h>
  38. #include <proto/dos.h>
  39. #include <proto/intuition.h>
  40. #include <proto/graphics.h>
  41. #endif
  42. #ifdef __GNUC__
  43. #include <inline/exec.h>
  44. #include <inline/dos.h>
  45. #include <inline/intuition.h>
  46. #include <inline/graphics.h>
  47. #endif
  48.  
  49. #define MAX_X 362
  50. #define MAX_Y_NTSC 241
  51. #define MAX_Y_PAL 283
  52.  
  53. #define MAPX(x) ((x) + offsetx)
  54. #define MAPY(y) (sh - (y) - 1 - offsety)
  55.  
  56. #define UNMAPX(x) ((x) - offsetx)
  57. #define UNMAPY(y) (sh - (y) - 1 - offsety)
  58.  
  59. static void Cleanup(void);
  60. static int IsPAL(void);
  61. static int CalcWidth(int);
  62. static int CalcHeight(int, int);
  63. static void MouseHandler(void);
  64. static void HandleIDCMP(void);
  65. static void StripIntuiMessages(struct MsgPort *, struct Window *);
  66. static struct MsgPort *CreatePort(UBYTE *, LONG);
  67. static void DeletePort(struct MsgPort *);
  68. static void SetupGrayMap(void);
  69. static void SetupColorMap(int);
  70.  
  71. struct GfxBase       *GfxBase = NULL;
  72. struct IntuitionBase *IntuitionBase = NULL;
  73.  
  74. static struct NewScreen screen = {
  75.   0, 0, 0, 0, 0, 0, 1, 0, AUTOSCROLL | CUSTOMSCREEN, NULL, NULL, NULL, NULL
  76. };
  77.  
  78. UWORD DriPens[] = { (UWORD)~0 };
  79.  
  80. static struct TagItem ScreenTags[] = {
  81. #define DISPIDTAG 0
  82.   {SA_DisplayID, NULL},
  83.   {SA_Overscan, OSCAN_VIDEO},
  84.   {SA_Pens, (ULONG)DriPens},
  85.   {TAG_DONE, NULL}
  86. };
  87.  
  88. static struct Image img = {
  89.   0, 0, 10, 10, 0, NULL, 0, 0, NULL
  90. };
  91.  
  92. static struct Gadget CloseGadget = {
  93.   NULL, 0, 0, 10, 10, GFLG_GADGHCOMP | GFLG_GADGIMAGE, GACT_RELVERIFY,
  94.   GTYP_BOOLGADGET, (APTR)&img, NULL, NULL, 0, NULL, 1, NULL
  95. };
  96.  
  97. static struct NewWindow window = {
  98.   0, 0, 0, 0, 0, 1, 0,
  99.   WFLG_SMART_REFRESH | WFLG_BACKDROP | WFLG_BORDERLESS | WFLG_RMBTRAP,
  100.   &CloseGadget, NULL, NULL, NULL, NULL, 0, 0, 0, 0, CUSTOMSCREEN
  101. };
  102.  
  103. static volatile struct Screen *s = NULL;
  104. static volatile struct Window *w = NULL;
  105. static struct RastPort *rp = NULL;
  106. static struct ViewPort *vp = NULL;
  107.  
  108. static int maxx, maxy, sw, sh, offsetx, offsety;
  109. static volatile int Done = 0;
  110. static struct Task *HandlerTask = NULL;
  111. static volatile int LMB=0;
  112. static volatile int MMB=0;
  113. static volatile int RMB=0;
  114. static volatile struct MsgPort *HandlerPort;
  115.  
  116. static int gray, max_colors;
  117.  
  118. void
  119. GraphicsInit(int xsize, int ysize, char *name, int gray)
  120. {
  121.   BYTE pal;
  122.  
  123.   atexit(Cleanup);
  124.   if ((GfxBase =
  125.       (struct GfxBase *) OpenLibrary ("graphics.library", 0L)) == NULL){
  126.     fprintf (stderr, "Can't open graphics.library\n");
  127.     Cleanup();
  128.     exit(RETURN_FAIL);
  129.   }
  130.  
  131.   if ((IntuitionBase =
  132.       (struct IntuitionBase *) OpenLibrary ("intuition.library", 0L)) == NULL){
  133.     fprintf (stderr, "Can't open intuition.library\n");
  134.     Cleanup();
  135.     exit(RETURN_FAIL);
  136.   }
  137.  
  138.   pal = IsPAL();
  139.   maxx = xsize - 1;
  140.   maxy = ysize - 1;
  141.   sw = CalcWidth(xsize);
  142.   screen.Width = sw;
  143.   sh = CalcHeight(ysize, pal);
  144.   screen.Height = sh;
  145.   screen.DefaultTitle = name;
  146.   offsetx = (sw - xsize) / 2;
  147.   offsety = (sh - ysize) / 2;
  148.   if (pal) {
  149.     screen.ViewModes =
  150.       ((sh > MAX_Y_PAL) ? LACE : 0) | ((sw > MAX_X) ? HIRES : 0);
  151.   }else{
  152.     screen.ViewModes =
  153.       ((sh > MAX_Y_NTSC) ? LACE : 0) | ((sw > MAX_X) ? HIRES : 0);
  154.   }
  155.   window.Width = sw, window.Height = sh;
  156.   ScreenTags[DISPIDTAG].ti_Data = screen.ViewModes;
  157.   if (pal) {
  158.     ScreenTags[DISPIDTAG].ti_Data |= PAL_MONITOR_ID;
  159.   }else{
  160.     ScreenTags[DISPIDTAG].ti_Data |= NTSC_MONITOR_ID;
  161.   }
  162.   if (gray) {
  163.     screen.Depth = 4;
  164.   }else{
  165.     if (screen.ViewModes & HIRES) {
  166.       screen.Depth = 3;
  167.     }else{
  168.       screen.Depth = 5;
  169.     }
  170.   }
  171.   if ((s = OpenScreenTagList (&screen, ScreenTags)) == NULL){
  172.     fprintf (stderr, "Can't open screen 1\n");
  173.     Cleanup();
  174.     exit(RETURN_FAIL);
  175.   }
  176.   ShowTitle (s, FALSE);
  177.   window.Screen = s;
  178.   if ((w = OpenWindow (&window)) == NULL){
  179.     fprintf (stderr, "Can't open window\n");
  180.     Cleanup();
  181.     exit(RETURN_FAIL);
  182.   }
  183.   vp = &(s->ViewPort);
  184.   rp = w->RPort;
  185.  
  186.   if (gray) {
  187.     SetupGrayMap();
  188.   }else{
  189.     SetupColorMap(screen.Depth);
  190.   }
  191.  
  192.   HandlerTask =
  193.     CreateTask("Raypaint Mouse Handler", 1, (APTR)MouseHandler, 10000);
  194. }
  195.  
  196. static void
  197. SetupGrayMap()
  198. {
  199.   int i;
  200.  
  201.   gray = 1;
  202.   for (i=0; i<16; i++) {
  203.     SetRGB4 (vp, i,  i, i, i);
  204.   }
  205. }
  206.  
  207. static void
  208. SetupColorMap(int depth)
  209. {
  210.   int col;
  211.   int r, g, b, red, green, blue;
  212.   double one_over_gamma = 0.4;
  213.  
  214.   gray = 0;
  215.   if (depth == 3) {
  216.     max_colors = 2;
  217.   }else{
  218.     max_colors = 3;
  219.   }
  220.   col = 0;
  221.   for (r = 0; r < max_colors; ++r) {
  222.     red = 15 * r / (max_colors-1);
  223.     for (g = 0; g < max_colors; ++g) {
  224.       green = 15 * g / (max_colors-1);
  225.       for (b = 0; b < max_colors; ++b) {
  226.         blue = 15 * b / (max_colors-1);
  227.     SetRGB4 (vp, col++,  red, green, blue);
  228.       }
  229.     }
  230.   }
  231. }
  232.  
  233. static int
  234. IsPAL(void)
  235. {
  236.   struct Screen *s;
  237.   ULONG mode;
  238.  
  239.   s = LockPubScreen("Workbench");
  240.   mode = GetVPModeID(&(s->ViewPort));
  241.   UnlockPubScreen(NULL, s);
  242.   if ((mode & PAL_MONITOR_ID) == PAL_MONITOR_ID){
  243.     return TRUE;
  244.   }
  245.   if ((mode & NTSC_MONITOR_ID) == NTSC_MONITOR_ID){
  246.     return FALSE;
  247.   }
  248.   /* Used to be this simple... */
  249.   return (GfxBase->DisplayFlags & PAL) ? TRUE : FALSE;
  250. }
  251.  
  252. static int
  253. CalcWidth(int width)
  254. {
  255.   if (width <= 320) return 320;
  256.   if (width <= MAX_X) return width;
  257.   if (width <= 640) return 640;
  258.   return width;
  259. }
  260.  
  261. static int
  262. CalcHeight(int height, int pal)
  263. {
  264.   if (pal) {
  265.     if (height <= 256) return 256;
  266.     if (height <= MAX_Y_PAL) return height;
  267.     if (height <= 512) return 512;
  268.     return height;
  269.   }else{
  270.     if (height <= 200) return 200;
  271.     if (height <= MAX_Y_NTSC) return height;
  272.     if (height <= 400) return 400;
  273.     return height;
  274.   }
  275. }
  276.  
  277. /*
  278.  * Draw the pixel at (xp, yp) in the color given by the rgb-triple,
  279.  * 0 indicating 0 intensity, 255 max intensity.
  280.  */
  281. void
  282. GraphicsDrawPixel(int xp, int yp, unsigned char color[3])
  283. {
  284.   int val;
  285.  
  286.   if (Done) {
  287.     Cleanup();
  288.     exit(RETURN_OK);
  289.   }
  290.  
  291.   if (gray) {
  292.     val = (((0.35*(double)(color[0]) +
  293.          0.55*(double)(color[1]) +
  294.          0.10*(double)(color[2])) * 15.0) / 255.0) + 0.5;
  295.   }else{
  296.     val = color[0] / 255.0 * (max_colors-1) + 0.5;
  297.     val *= max_colors;
  298.     val += color[1] / 255.0 * (max_colors-1) + 0.5;
  299.     val *= max_colors;
  300.     val += color[2] / 255.0 * (max_colors-1) + 0.5;
  301.   }
  302.   SetAPen(rp, val);
  303.   WritePixel(rp, MAPX(xp), MAPY(yp));
  304. }
  305.  
  306. /*
  307.  * Draw the rect with lower left corner (xp, yp) and upper right
  308.  * corner (xp+ys, yp+ys).  The colors of the l-l, l-r, u-r, and u-l
  309.  * corners are given as arrays of unsigned chars as above.
  310.  */
  311. void
  312. GraphicsDrawRectangle(int xp, int yp, int xs, int ys,
  313.                       unsigned char ll[3], unsigned char lr[3], 
  314.                       unsigned char ur[3], unsigned char ul[3])
  315. {
  316.   int val;
  317.  
  318.   if (Done) {
  319.     Cleanup();
  320.     exit(RETURN_OK);
  321.   }
  322.   if (gray) {
  323.     val = (((0.35*(double)(ll[0]) +
  324.          0.55*(double)(ll[1]) +
  325.          0.10*(double)(ll[2])) * 15.0) / 255.0) + 0.5;
  326.   }else{
  327.     val = ll[0] / 255.0 * (max_colors-1) + 0.5;
  328.     val *= max_colors;
  329.     val += ll[1] / 255.0 * (max_colors-1) + 0.5;
  330.     val *= max_colors;
  331.     val += ll[2] / 255.0 * (max_colors-1) + 0.5;
  332.   }
  333.   SetAPen(rp, val);
  334.   RectFill(rp, MAPX(xp), MAPY(yp+ys), MAPX(xp+xs), MAPY(yp));
  335. }
  336.  
  337. int
  338. GraphicsRedraw(void)
  339. {
  340.   /* This is a SMART_REFRESH window;
  341.      We don't have to worry about redrawing it */
  342.   return 0;
  343. }
  344.  
  345. void
  346. GraphicsGetMousePos(int *x, int *y)
  347. {
  348.   *x = UNMAPX(w->MouseX);
  349.   *y = UNMAPY(w->MouseY);
  350.   if (*x < 0) {
  351.     *x = 0;
  352.   }
  353.   if (*x > maxx) {
  354.     *x = maxx;
  355.   }
  356.   if (*y < 0) {
  357.     *y = 0;
  358.   }
  359.   if (*y > maxy) {
  360.     *y = maxy;
  361.   }
  362. }
  363.  
  364. int
  365. GraphicsLeftMouseEvent(void)
  366. {
  367.   return LMB;
  368. }
  369.  
  370. int
  371. GraphicsRightMouseEvent(void)
  372. {
  373.   return RMB;
  374. }
  375.  
  376. int
  377. GraphicsMiddleMouseEvent(void)
  378. {
  379.   return MMB || (LMB && RMB);
  380. }
  381.  
  382. static void
  383. Cleanup(void)
  384. {
  385.   if (HandlerTask) {
  386.     Signal(HandlerTask, 1 << HandlerPort->mp_SigBit);
  387.     Delay(2);
  388.     HandlerTask = NULL;
  389.   }
  390.   if (w) {
  391.     CloseWindow(w);
  392.     w = NULL;
  393.   }
  394.   if (s) {
  395.     CloseScreen(s);
  396.     s = NULL;
  397.   }
  398.   if (GfxBase) {
  399.     CloseLibrary((struct Library *)GfxBase);
  400.   }
  401.   if (IntuitionBase) {
  402.     CloseLibrary ((struct Library *)IntuitionBase);
  403.   }
  404. }
  405.  
  406. static void
  407. MouseHandler(void)
  408. {
  409.   ULONG winsignalmask, portsignalmask, signals;
  410.   struct MsgPort *IDCMPPort;
  411.   struct IntuitionBase *IntuitionBase;
  412.  
  413.   IntuitionBase =
  414.     (struct IntuitionBase *) OpenLibrary ("intuition.library", 0L);
  415.   IDCMPPort = CreatePort("RayPaint IDCMP Port", 0);
  416.   w->UserPort = IDCMPPort;
  417.   ModifyIDCMP(w, IDCMP_GADGETUP | IDCMP_MOUSEBUTTONS);
  418.  
  419.   HandlerPort = CreatePort("RayPaint Handler Port", 0);
  420.  
  421.   for(;;){
  422.     winsignalmask  = 1L << w->UserPort->mp_SigBit;
  423.     portsignalmask = 1L << HandlerPort->mp_SigBit;
  424.  
  425.     signals = Wait(winsignalmask | portsignalmask);
  426.     if (signals & winsignalmask) {
  427.       HandleIDCMP();
  428.     }
  429.     if (signals & portsignalmask){
  430.       Forbid();
  431.       StripIntuiMessages(w->UserPort, w);
  432.       w->UserPort = NULL;
  433.       ModifyIDCMP(w, 0);
  434.       Permit();
  435.       DeletePort(IDCMPPort);
  436.       DeletePort(HandlerPort);
  437.       CloseLibrary ((struct Library *)IntuitionBase);
  438.       Done = 1;
  439.       return;
  440.     }
  441.   }
  442. }
  443.  
  444. static void
  445. HandleIDCMP(void)
  446. {
  447.   struct IntuiMessage *message;
  448.   ULONG class;
  449.   USHORT code;
  450.  
  451.   while (message = (struct IntuiMessage *)GetMsg(w->UserPort)) {
  452.     class = message->Class;
  453.     code = message->Code;
  454.  
  455.     switch(class) {
  456.       case IDCMP_GADGETUP:
  457.         Done = 1;
  458.         break;
  459.       case IDCMP_MOUSEBUTTONS:
  460.         switch(code) {
  461.       case SELECTUP:
  462.         LMB = 0;
  463.         break;
  464.       case SELECTDOWN:
  465.         LMB = 1;
  466.         break;
  467.       case MENUUP:
  468.         RMB = 0;
  469.         break;
  470.       case MENUDOWN:
  471.         RMB = 1;
  472.         break;
  473.       case MIDDLEUP:
  474.         MMB = 0;
  475.         break;
  476.       case MIDDLEDOWN:
  477.         MMB = 1;
  478.         break;
  479.         }
  480.         break;
  481.     }
  482.     ReplyMsg((struct Message *)message);
  483.   }
  484. }
  485.  
  486. static void
  487. StripIntuiMessages(struct MsgPort *mp, struct Window *win)
  488. {
  489.   struct IntuiMessage *msg;
  490.   struct Node *succ;
  491.  
  492.   msg = (struct IntuiMessage *)mp->mp_MsgList.lh_Head;
  493.  
  494.   while (succ = msg->ExecMessage.mn_Node.ln_Succ) {
  495.     if (msg->IDCMPWindow == win) {
  496.       Remove((struct Node*)msg);
  497.       ReplyMsg((struct Message *)msg);
  498.     }
  499.     msg = (struct IntuiMessage *)succ;
  500.   }
  501. }
  502.  
  503. static struct MsgPort *
  504. CreatePort(UBYTE *name, LONG pri)
  505. {
  506.   struct MsgPort *newmp;
  507.  
  508.   if (newmp = CreateMsgPort()) {
  509.     newmp->mp_Node.ln_Name = name;
  510.     newmp->mp_Node.ln_Pri = pri;
  511.     AddPort(newmp);
  512.   }
  513.   return newmp;
  514. }
  515.  
  516. static void
  517. DeletePort(struct MsgPort *mp)
  518. {
  519.   if (mp) {
  520.     if (mp->mp_Node.ln_Name) {
  521.       RemPort(mp);
  522.     }
  523.     DeleteMsgPort(mp);
  524.   }
  525. }
  526.